﻿using System.Collections.Generic;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Xml;
using SHomeWorkshop.LunarPresentation.Interfaces;
using SHomeWorkshop.LunarPresentation.Widegets;

namespace SHomeWorkshop.LunarPresentation.Expressions
{
    /// <summary>
    /// 这是一个中间类。
    /// 是为“要嵌入子面板的控件”准备的包装类——但不直接包括子面板。
    /// 为使公式中可以嵌入子面板或其它内容，此类的Child是一个Canvas，
    /// </summary>
    public abstract class CanvasExpression : Expression, ICollapsed
    {
        public CanvasExpression(SubPanel rootPanel, SubPanel parentPanel, Editor editor)
            : base(rootPanel, parentPanel, editor)
        {
            this.basePanel = new Canvas();
            //this.basePanel.Focusable = false;
            this.mainBorder.Child = basePanel;

            //为鼠标提供的矩形。
            baseRectangle = new Rectangle();
            baseRectangle.Cursor = System.Windows.Input.Cursors.Hand;
            baseRectangle.Stroke = Brushes.Transparent;
            baseRectangle.Fill = Brushes.Transparent;
            baseRectangle.MouseRightButtonDown += new MouseButtonEventHandler(baseRectangle_MouseRightButtonDown);
            baseRectangle.MouseLeftButtonDown += new MouseButtonEventHandler(baseRectangle_MouseLeftButtonDown);
            baseRectangle.MouseLeftButtonUp += new MouseButtonEventHandler(baseRectangle_MouseLeftButtonUp);

            basePanel.Children.Add(baseRectangle);
            Canvas.SetZIndex(baseRectangle, 0);

            this.basePanel.SizeChanged += new System.Windows.SizeChangedEventHandler(basePanel_SizeChanged);

            this.subPanels = new List<SubPanel>();
        }

        public UIElementCollection Children
        {
            get { return this.basePanel == null ? null : this.basePanel.Children; }
        }

        void baseRectangle_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            // 接收拖动来的公式。
            Globals.DropExpression(this);
        }

        void baseRectangle_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            //准备拖动公式。
            Globals.dragSourceExpression = this;
            this.Editor.SelectedExpression = this;
            e.Handled = true;
        }

        void basePanel_SizeChanged(object sender, System.Windows.SizeChangedEventArgs e)
        {
            if (e.WidthChanged)
                baseRectangle.Width = basePanel.Width;

            if (e.HeightChanged)
                baseRectangle.Height = basePanel.Height;
        }

        void baseRectangle_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
        {
            this.Editor.SelectedExpression = this;
            e.Handled = true;
        }

        /// <summary>
        /// 子类必须注意此矩形何时更改尺寸填充。
        /// </summary>
        protected Rectangle baseRectangle;

        protected Canvas basePanel;

        public Canvas BasePanel
        {
            get { return basePanel; }
        }

        /// <summary>
        /// SubPanels属性用以在公式各层间导航，不是所有公式内部都嵌入子面板，
        /// 因此不是所有公式均需要本方法。
        /// 
        /// 在实际公式类，此一方法应设置：FirstSubPanel/LastSubPanel/SubPanels
        /// 这三个属性的值。
        /// </summary>
        protected abstract void RefreshSubPanelRelatios();

        protected override void BuildChildren()
        {
            base.BuildChildren();

            XmlAttribute attrIsCollapsed = this.XmlData.GetAttribute("IsCollapsed");
            if (attrIsCollapsed != null)
            {
                this.isCollapsed = bool.Parse(attrIsCollapsed.Value);
                this.RefreshIsCollapsed();
            }
        }

        public override string CommentText
        {
            get
            {
                return base.CommentText;
            }
            set
            {
                base.CommentText = value;
                if (isCollapsed && exCollapseMark != null)
                {
                    exCollapseMark.RefreshExCollpseMarkText();
                }
            }
        }

        #region ICollpased接口的实现代码。

        private ExCollapseMark exCollapseMark;

        private bool isCollapsed = false;

        public bool IsCollapsed
        {
            get { return isCollapsed; }
            set
            {
                isCollapsed = value;
                RefreshIsCollapsed();

                this.XmlData.SetAttribute("IsCollapsed", isCollapsed.ToString());

                Editor.IsModified = true;
            }
        }

        private void RefreshIsCollapsed()
        {
            if (isCollapsed)
            {
                if (exCollapseMark == null)
                {
                    exCollapseMark = new ExCollapseMark(this);
                }

                exCollapseMark.RefreshExCollpseMarkText();
                this.mainBorder.Child = exCollapseMark;
            }
            else
            {
                this.mainBorder.Child = basePanel;
                this.exCollapseMark = null;
            }

            this.InvalidateVisual();
        }

        #endregion

        public override Brush ExForeground
        {
            get
            {
                return base.ExForeground;
            }
            set
            {
                UpdateExForegroundWithoutXmlChanging(value);
                UpdateExForegroundToXmlData(value);
                Editor.IsModified = true;
            }
        }

        public override void UpdateExForegroundWithoutXmlChanging(Brush value)
        {
            base.UpdateExForegroundWithoutXmlChanging(value);

            base.exForeground = value;

            if (this.exCollapseMark != null)
            {
                this.exCollapseMark.UpdateForeground();
            }
        }

        public override void SetProperty(string propertyName, string value)
        {
            if (propertyName == null || propertyName.Length <= 0) return;
            base.SetProperty(propertyName, value);

            switch (propertyName)
            {
                case "IsCollapsed":
                    {
                        this.IsCollapsed = bool.Parse(value);
                        break;
                    }
            }
        }
    }
}
